//***************************************************************************
//   Copyright(c)2020, Xidian University D405.
//   All rights reserved
//
//   IP Name         :   Null
//   File name       :   np_dma_rx_polling.v
//   Module name     :   np_dma_rx_polling
//   Author          :   Wang Zekun
//   Date            :   2022/05/17
//   Version         :   v1.4
//   Verison History :   v1.0/v1.1/v1.2/1.3/1.4
//   Edited by       :   Wang Zekun
//   Modification history : v1.0 Initial revision
//                          v1.1 modify counter initial value,2'b00--->2'b01
//                          v1.2 use empty_r as judging rolling condition,and add double empty rolling method
//                          v1.3 Add port_sel_for_leng_fifo and rxfifo_data_empty*_i, fix polling method.
//                          v1.4 Make Code Simple Again.
// ----------------------------------------------------------------------------
// Version 1.20      Date(2022/04/22)
// Abstract : Polling 10G/40G rx fifo data
//-----------------------------------------------------------------------------
// Programmer's model
//                    Null
//-----------------------------------------------------------------------------
//interface list :
//                
module np_dma_rx_polling (
  input  wire                clk_i,
  input  wire                resetn_i,
  input  wire                rxfifo_empty0_i,
  input  wire                rxfifo_data_empty0_i,
  input  wire                rxfifo_empty1_i,
  input  wire                rxfifo_data_empty1_i,
  input  wire                almost_done_i,
  input  wire                already_done_i,
  input  wire                rxfifo_rd_leng_en_i,
  output wire                port_sel_o,
  output wire                port_sel_for_leng_fifo_o,
  input  wire                data_sel_lock_i
);
  reg                     port_sel_r;
  reg                     port_sel_for_leng_fifo;
  reg                     port_sel_for_leng_fifo_r;
  reg [4:0]               polling_cnt;
  reg                     polling_cnt_clr;
  wire                    polling_cnt_en;

  always @(posedge clk_i or negedge resetn_i) begin
    if(~resetn_i)
      polling_cnt_clr <= 1'b0;
    else
      polling_cnt_clr <= rxfifo_data_empty0_i | rxfifo_data_empty1_i;
  end

  always @(*) begin
    if(rxfifo_empty0_i & ~rxfifo_empty1_i)
      port_sel_for_leng_fifo = 1'b1;             // select 40G
    else if(rxfifo_empty1_i & ~rxfifo_empty0_i)
      port_sel_for_leng_fifo = 1'b0;             // select 10G
    else if(~rxfifo_empty1_i & ~rxfifo_empty0_i & rxfifo_rd_leng_en_i)
      port_sel_for_leng_fifo = (polling_cnt != 5'b00001);      // normal polling
    else
      port_sel_for_leng_fifo = 1'b1;
  end

  always @(posedge clk_i or negedge resetn_i) begin
    if(~resetn_i)
      port_sel_for_leng_fifo_r <= 1'b0;
    else if(rxfifo_rd_leng_en_i)
      port_sel_for_leng_fifo_r <= port_sel_for_leng_fifo;
    else
      port_sel_for_leng_fifo_r <= port_sel_for_leng_fifo_r;
  end

  assign port_sel_for_leng_fifo_o = port_sel_for_leng_fifo_r;

  always @(posedge clk_i or negedge resetn_i)
  begin
    if(~resetn_i)
      port_sel_r <= 1'b0;
    else if(data_sel_lock_i)
      port_sel_r <= port_sel_r;
    else
      port_sel_r <= port_sel_for_leng_fifo_r;
  end

  assign port_sel_o = port_sel_r;

  always @(posedge clk_i or negedge resetn_i) begin
    if(~resetn_i)
      polling_cnt <= 5'b00001;
    else if(polling_cnt_clr)
      polling_cnt <= 5'b00001;               // anyone fifo empty
    else if(polling_cnt_en)
      polling_cnt <= {polling_cnt[3:0], polling_cnt[4]};
    else
      polling_cnt <= polling_cnt;
  end

  assign polling_cnt_en  = almost_done_i;

endmodule
